

#pragma once

#include "CEGUIOwner.h"
#include <CEGUI/CEGUI.h>
#include <OgreCEGUIRenderer.h>

#include <Ogre.h>

#include "IGameState.h"
#include "CameraController.h"
#include "DebuggeableState.h"

#include <NxOgre.h>

#include "Tangible.h"

#include "Control.h"

#include "ObjectsManager.h"
#include "EffectsManager.h"

#include "ListenerDeJuego.h"

#include "IEventListener.h"

#include "ObjectTextDisplay.h"

#include "EstadoAI.h"

#include <boost/weak_ptr.hpp>

#include "ColoredTextAreaOverlayElement.h"

#include "ManagerDeMisiones.h"

#include "DynamicLines.h"

class MainGameState : 
	public IGameState,
	private CEGUIOwner,
	private DebuggeableState,
	public NxOgre::ActorContactCallback
{
	Ogre::SceneManager * mSceneMgr;
	Ogre::Camera * mCamera;
	Ogre::Viewport * mViewport;

	//! Target attributes
	Ogre::Camera * mTargetCamera;
	Ogre::Viewport * mTargetViewport;


	NxOgre::World * mWorld;
	NxOgre::Scene * mNxScene;

	boost::weak_ptr<Unidad> mPlayerShip;

	ObjectTextDisplay * mTextDisplay;
	Ogre::TextAreaOverlayElement * mInfoOverlay;
	Ogre::TextAreaOverlayElement * mPlayerShipOverlay;
	Ogre::TextAreaOverlayElement * mTargetsOverlay;

	DynamicLines * mTargetLine;
	Ogre::ManualObject * mLineObject;

	int mDifficulty;

	boost::scoped_ptr<CameraControl> mCameraControl;

	bool mGameOver, mGameWin;

	//! Events, tasks, etc, which belong to the game state.
	Control mCtrl;

	//! Manages game objects.
	ObjectsManager::Ptr mObjectsManager;

	//! Manages game effects.
	EffectsManager::Ptr mManagerDeEfectos;

	//! Listener which deals with game events.
	IEventListener::Ptr mListenerDeJuego; 

	//! Missions manager.
	ManagerDeMisiones::Ptr mManagerDeMisiones;


	//! True if the game is paused.
	bool mPaused;

public:


	//! Returns a pointer to the overlay which shows the objectives.
	//!
	Ogre::TextAreaOverlayElement * GetOverlayObjetivos()
	{
		return mTargetsOverlay;
	}


	Ogre::ManualObject * GetLineaObjetivo() { return mLineObject; }

	//! Returns a pointer to the missions manager.
	//!
	ManagerDeMisiones * GetManagerDeMisiones() { return mManagerDeMisiones.get(); }

	//! Returns the difficulty level.
	//!
	int GetDificultad() const
	{
		return mDifficulty;
	}

	//! Configures the difficulty level.
	//!
	void SetDificultad(int niv)
	{
		mDifficulty = niv;
	}

	//! Configures the camera.
	//!
	void ConfigurarCamara();

	//! Returns a pointer to the player's ship, or null.
	//!
	Unidad * GetShipJugador()
	{
		return mPlayerShip.lock().get();
	}

	//! Creates the player's ship.
	//!
	void CrearShipJugador();

	//! Returns the objects manager.
	//!
	ObjectsManager * GetObjectsManager()
	{
		return mObjectsManager.get();
	}

	//! Returns a reference to the local Control object.
	//!
	Control & GetControl() { return mCtrl; }

	//! Returns the scene manager.
	//! 
	Ogre::SceneManager * GetSceneManager() { return mSceneMgr; }

	//! Returns the camera.
	//! 
	Ogre::Camera * GetCamera() { return mCamera; }

	//! Returns the NxOgre physical scene.
	//!
	NxOgre::Scene * GetPhysScene() { return mNxScene; }

	//! Returns the camera controller.
	//!
	CameraControl * GetCameraControl() { return mCameraControl.get(); }


	MainGameState(BaseGameManager & gameManager);

	//! Returns the visual and physical scene.
	//!
	void CrearEscena();

	virtual const char * GetStateName();

	//! Called when entering the game state.
	//!
	virtual void OnEnter();

	//! Creates the CEGUI menu.
	//!
	void CrearGUI();

	//! Called every frame.
	//!
	virtual bool OnFrameStarted(Ogre::FrameEvent const & evt);

	//! Updates those things related to the current target.
	//!
	void ActualizarObjetivo();

	//! Called automatically upon game state exit.
	//! We completely destroy whatever's been created OnEnter.
	virtual void OnExit();

	virtual void OnKeyPressed(OIS::KeyEvent const & e);

	virtual void OnKeyReleased(OIS::KeyEvent const & e);

	virtual bool OnMousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id);

	virtual bool OnMouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id);

	virtual bool OnMouseMoved(const OIS::MouseEvent &e);


	/* GUI events */



	bool OnGUISalir(const CEGUI::EventArgs & e);


	bool OnGUIComenzar(const CEGUI::EventArgs & e);


	/* Physical events */

	void onBeginContact(NxOgre::Actor*, NxOgre::Actor*, NxContactPair&);

	void onEndContact(NxOgre::Actor*, NxOgre::Actor*, NxContactPair&)
	{		
		std::cout << "EndContact" << std::endl;
	}

	void onContact(NxOgre::Actor*, NxOgre::Actor*, NxContactPair&)
	{		
		std::cout << "OnContact" << std::endl;
	}
};